package cn.lingyangwl.agile.infra.gen.template;

import cn.lingyangwl.agile.infra.gen.template.converter.ColumnTypeConverter;
import cn.lingyangwl.agile.infra.gen.utils.FieldUtil;
import cn.lingyangwl.framework.tool.core.InputCoder;
import cn.lingyangwl.framework.tool.core.StringUtils;
import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 表字段信息
 * @author shenguangyang
 */
@Slf4j
@Getter
@Setter
public class TmplColumnDefinition {
    /**
     * 数据库字段名
     */
    private String columnName;
    /**
     * 数据库类型
     */
    private String type;
    /**
     * 是否自增
     */
    private Boolean isIdentity = Boolean.FALSE;
    /**
     * 是否主键
     */
    private Boolean isPk = Boolean.FALSE;
    /**
     * 字段注释
     */
    private String comment;
    /**
     * 字段长度
     */
    private Integer length;
    /**
     * 小数位长度
     */
    private Integer scale;

    /**
     * 属性名
     */
    private String attrName;

    /**
     * 字段是否允许为null
     */
    private Boolean isNullable = Boolean.FALSE;

    /**
     * 是否为插入字段
     */
    private Boolean isInsert = Boolean.FALSE;

    /**
     * 是否编辑字段
     */
    private Boolean isEdit = Boolean.FALSE;

    /**
     * 是否列表字段
     */
    private Boolean isList = Boolean.FALSE;

    /**
     * 是否查询字段
     */
    private Boolean isQuery = Boolean.FALSE;

    /**
     * 是否为详情字段
     */
    private Boolean isDetail = Boolean.FALSE;

    /**
     * 查询方式（EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围）
     */
    private String queryType;

    /**
     * 显示类型, 直接写vue等组件名称即可
     */
    private String htmlType;

    /**
     * 字典类型
     */
    private String dictType;


    /**
     * 数据库字段名首字母小写
     */
    public String getColumnNameLF() {
        return FieldUtil.lowerFirstLetter(this.columnName);
    }

    public String getLabel() {
        return StringUtils.isNotEmpty(comment) ? comment : columnName;
    }

    /**
     * 获得基本类型,int,float
     *
     * @return 返回基本类型
     */
    public String getFieldType() {
        return getColumnTypeConverter().convertType(type);
    }

    /**
     * 获得装箱类型,Integer,Float
     *
     * @return 返回装箱类型
     */

    public String getFieldTypeBox() {
        return getColumnTypeConverter().convertTypeBox(getType());
    }

    /**
     * 是否是自增主键
     *
     * @return true, 是自增主键
     */
    public boolean getIsIdentityPk() {
        return getIsPk() && getIsIdentity();
    }

    public void setComment(String comment) {
        if (comment == null) {
            comment = "";
        }
        this.comment = comment;
    }

    /**
     * 输入表字段拼音 返回 java字段名
     *
     * 对应一些特殊业务, 比如医疗系统或者其他系统, 他们都有一个共同特点就是专业术语太多, 如果完全用
     * 英文命名字段是有一定困难(你英语非常好除外), 这时就需要通过当前方法获取java字段名
     *
     * 命名规则如下: 前两个汉字全拼, 第一个拼音小写, 第二个拼音首字母大写其余小写, 其他汉字取拼音首字母且大写
     * <p>
     * eg:
     *  数据库: columnComment - 你好啊,  columnName - nihaoa <br/>
     *  java字段(也是当前方法返回值): niHaoA
     * </p>
     * </br>
     * 你也可以根据你们项目的命名规则进行自定义
     */
    public String getPinYinFieldName() {
        try {
            // 只保留汉字其余特殊符号会被去掉
            String chinaColumnComment =  StringUtils.retainChinese(this.comment);
            List<String> pinYinList = new ArrayList<>();
            for (int i = 0; i < chinaColumnComment.length(); i++) {
                char c1 = chinaColumnComment.charAt(i);
                String fullSpell = InputCoder.getFullSpell(String.valueOf(c1));
                pinYinList.add(fullSpell);
            }
            String tempTableColumnName = this.columnName;
            StringBuilder fieldNameSb = new StringBuilder("");
            for (String pinYin : pinYinList) {
                if (StringUtils.isEmpty(pinYin)) {
                    continue;
                }
                String tempPinYin = pinYin;
                if (tempTableColumnName.contains(tempPinYin)) {
                    // 判断是否进行第一个拼音小写操作
                    if ("".equals(fieldNameSb.toString())) {
                        fieldNameSb.append(tempPinYin.toLowerCase(Locale.ROOT));
                    } else {
                        // 首字母大写其余小写
                        tempPinYin = tempPinYin.substring(0, 1).toUpperCase(Locale.ROOT) + tempPinYin.substring(1).toLowerCase(Locale.ROOT);
                        fieldNameSb.append(tempPinYin);
                    }
                } else {
                    fieldNameSb.append(tempTableColumnName.toUpperCase(Locale.ROOT));
                    break;
                }
                tempTableColumnName = tempTableColumnName.replace(pinYin, "");
            }
            return fieldNameSb.toString();
        } catch (Exception e) {
            log.error("columnDefinition: {}", JSON.toJSONString(this));
            throw new RuntimeException(e);
        }
    }

    public ColumnTypeConverter getColumnTypeConverter() {
        throw new UnsupportedOperationException("未覆盖cn.fscode.code.generator.gen.ColumnDefinition.getColumnTypeConverter方法");
    }
}
